package com.ruoyi.business.service.impl;


import com.ruoyi.business.mapper.*;
import com.ruoyi.business.service.IFinancialOverviewService;
import com.ruoyi.business.service.IWsdCanteenBalanceService;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.entity.WsdGrades;
import com.ruoyi.common.core.domain.entity.WsdSchools;
import com.ruoyi.common.core.domain.vo.*;
import com.ruoyi.common.utils.date.DateTimeUtil;

import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.ruoyi.common.utils.PageUtils.startPage;
import static com.ruoyi.common.utils.SecurityUtils.getLoginUser;


/**
 * 财务概况
 */
@Service
public class FinancialOverviewServiceImpl implements IFinancialOverviewService
{
    @Autowired
    private IWsdCanteenBalanceService wsdCanteenBalanceService;
    @Autowired
    private WsdLeavesMapper wsdLeavesMapper;
    @Autowired
    private WsdRefundTransactionsMapper wsdRefundTransactionsMapper;
    @Autowired
    private WsdRechargeRefundMapper wsdRechargeRefundMapper;
    @Autowired
    private WsdCanteenBalanceMapper wsdCanteenBalanceMapper;
    @Autowired
    private WsdPaymentRecordsMapper wsdPaymentRecordsMapper;
    @Autowired
    private WsdGradesMapper wsdGradesMapper;
    @Autowired
    private WsdSchoolsMapper wsdSchoolsMapper;
    /**
     * 第一层数据统计
     * @param
     * @param startDate
     * @param endDate
     * @return
     */
    @Override
    public FinancialOverviewVO firstleve(LocalDateTime startDate, LocalDateTime endDate){
        FinancialOverviewVO financialOverviewVO = new FinancialOverviewVO();
        Long schoolId = null;
        Integer type = 0;
        Integer mealLeaves = 0 ;
        SysUser sysUser = getLoginUser().getUser();
        if (sysUser.getSchoolId()==null){
            return financialOverviewVO;
        }
        if (!sysUser.isAdmin()){
            schoolId = sysUser.getSchoolId();
            type = 1;
        }
        Date start = Date.from(startDate.atZone( ZoneId.systemDefault()).toInstant());
        Date end = Date.from(endDate.atZone( ZoneId.systemDefault()).toInstant());
        Long configId = wsdRechargeRefundMapper.getConfigId(start,end,schoolId);
        if (configId==null){
            configId = -1L;
        }
        if (type==0){
            //admin
            Integer add = 0 ;
            WsdSchools wsdSchools = new WsdSchools();
            List<FinancialOrderFoodVO> financialOrderFoodVOList = wsdSchoolsMapper.selectWsdSchoolsLists(wsdSchools);
            for (FinancialOrderFoodVO financialOrderFoodVO : financialOrderFoodVOList) {
                Long configId2 = wsdRechargeRefundMapper.getConfigId(start, end, financialOrderFoodVO.getSchoolId());
                Integer a = wsdCanteenBalanceMapper.selectStudentCount(financialOrderFoodVO.getSchoolId(), configId2);
                if (a==null){
                    a = 0;
                }
                add=add+a;
            }
            financialOverviewVO.setMealLeaves(add);
            mealLeaves = add;
        }else {
            //订餐人数
            mealLeaves = wsdCanteenBalanceMapper.selectStudentCount(schoolId, configId);
            if (mealLeaves == null) {
                mealLeaves = 0;
            }
            financialOverviewVO.setMealLeaves(mealLeaves);
        }
        //实际就餐人数
        Integer TotalLeaves  = wsdLeavesMapper.countTodayPeoples(schoolId,startDate,endDate);
        Integer diningLeaves = mealLeaves-TotalLeaves;
        if (diningLeaves<0){
            diningLeaves = 0;
        }
        financialOverviewVO.setDiningLeaves( diningLeaves );

        //请假人数
        financialOverviewVO.setTotalLeaves( TotalLeaves );

        //退餐人数
        Integer refunded = wsdLeavesMapper.refunded(schoolId,startDate,endDate);
        financialOverviewVO.setRefunded( refunded );

        //退餐金额
        BigDecimal refundedMoney = wsdRefundTransactionsMapper.refundedMoney(schoolId,startDate,endDate);
        if (refundedMoney==null){
            refundedMoney = BigDecimal.ZERO;
        }
        financialOverviewVO.setRefundedMoney( refundedMoney );

        return financialOverviewVO;
    }
    /**
     * 第二层
     */
    //退款金额统计
    @Override
    public ChartDataBVO returnAmount(Integer type,LocalDateTime startDate, LocalDateTime endDate) {
        Long schoolId = null;
        SysUser sysUser = getLoginUser().getUser();
        if (!sysUser.isAdmin()) {
            schoolId = sysUser.getSchoolId();
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        //生成日期
        Date start = Date.from(startDate.atZone(ZoneId.systemDefault()).toInstant());
        Date end = Date.from(endDate.atZone(ZoneId.systemDefault()).toInstant());
        String dateString2 = sdf.format(start);
        String dateString1 = sdf.format(end);
        RechargeRefundVO existsActive = wsdRechargeRefundMapper.existsActive(dateString2, dateString1, schoolId);
        List<String> labels = new ArrayList<>();
        List<Integer> values = new ArrayList<>();
        List<Integer> values2 = new ArrayList<>();
        List<Map<String, Object>> monthlyData = new ArrayList<>();
        if (type == 3) {
            // 创建一个包含12个月的月份列表
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.DAY_OF_MONTH, 1);
            int daysInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
            for (int i = 1; i <= daysInMonth; i++) {
                labels.add(i + "号");
                values.add(0);
                values2.add(0);
            }
            if (existsActive==null){
                WsdSchools wsdSchools = new WsdSchools();
                List<FinancialOrderFoodVO> financialOrderFoodVOList = wsdSchoolsMapper.selectWsdSchoolsLists(wsdSchools);
                for (FinancialOrderFoodVO financialOrderFoodVO : financialOrderFoodVOList) {
                    monthlyData = wsdLeavesMapper.mealNum(financialOrderFoodVO.getSchoolId(), startDate, endDate);
                    existsActive = wsdRechargeRefundMapper.existsActive(dateString2, dateString1, financialOrderFoodVO.getSchoolId());
                    for (Map<String, Object> record : monthlyData) {
                        Date rechargeDate = (Date) record.get("rechargeDate");
                        String dateString = extractDay(sdf.format(rechargeDate));
                        Integer month = Integer.valueOf(dateString);
                        //餐数
                        Long morningFee = (Long) record.get("breakfastLeave");
                        Long lunchFee = (Long) record.get("lunchLeave");
                        BigDecimal morningFeeDecimal = BigDecimal.valueOf(morningFee);
                        BigDecimal lunchFeeBigDecimal = BigDecimal.valueOf(lunchFee);
                        BigDecimal resultmorning = existsActive.getBreakfastFee().multiply(morningFeeDecimal);
                        BigDecimal resultlunch = existsActive.getLunchFee().multiply(lunchFeeBigDecimal);
                        //计算金额
                        int oldValueMorning = values.get(month - 1);
                        int newValueMorning = oldValueMorning + resultmorning.intValue();
                        int oldValueLunch = values2.get(month - 1);
                        int newValueLunch = oldValueLunch + resultlunch.intValue();
                        values.set(month - 1, newValueMorning);
                        values2.set(month - 1, newValueLunch);
                    }
                }
            }else {
                monthlyData = wsdLeavesMapper.mealNum(schoolId, startDate, endDate);
                // 更新列表中的数据
                for (Map<String, Object> record : monthlyData) {
                    Date rechargeDate = (Date) record.get("rechargeDate");
                    String dateString = extractDay(sdf.format(rechargeDate));
                    Integer month = Integer.valueOf(dateString);
                    //餐数
                    Long morningFee = (Long) record.get("breakfastLeave");
                    Long lunchFee = (Long) record.get("lunchLeave");
                    BigDecimal morningFeeDecimal = BigDecimal.valueOf(morningFee);
                    BigDecimal lunchFeeBigDecimal = BigDecimal.valueOf(lunchFee);
                    BigDecimal resultmorning = existsActive.getBreakfastFee().multiply(morningFeeDecimal);
                    BigDecimal resultlunch = existsActive.getLunchFee().multiply(lunchFeeBigDecimal);
                    //计算金额
                    values.set(month - 1, resultmorning.intValue());
                    values2.set(month - 1, resultlunch.intValue());
                }
            }
        }else {
            List<String> formattedDates = getFormattedDatesBetween(startDate, endDate);
            for (String a : formattedDates) {
                labels.add(a);
                values.add(0);
                values2.add(0);
            }
            if (existsActive==null){
                WsdSchools wsdSchools = new WsdSchools();
                List<FinancialOrderFoodVO> financialOrderFoodVOList = wsdSchoolsMapper.selectWsdSchoolsLists(wsdSchools);
                for (FinancialOrderFoodVO financialOrderFoodVO : financialOrderFoodVOList) {
                    monthlyData = wsdLeavesMapper.mealNum(financialOrderFoodVO.getSchoolId(), startDate, endDate);
                    existsActive = wsdRechargeRefundMapper.existsActive(dateString2, dateString1, financialOrderFoodVO.getSchoolId());
                    for (Map<String, Object> record : monthlyData) {
                        Date rechargeDate = (Date) record.get("rechargeDate");
                        String dateString = extractDay(sdf.format(rechargeDate));
                        int index = -1; // 初始化下标为-1，表示未找到匹配项
                        for (int i = 0; i < labels.size(); i++) {
                            if (labels.get(i).equals(dateString)) {
                                index = i;
                                break; // 找到匹配项后退出循环
                            }
                        }
                        //餐数
                        Long morningFee = (Long) record.get("breakfastLeave");
                        Long lunchFee = (Long) record.get("lunchLeave");
                        BigDecimal morningFeeDecimal = BigDecimal.valueOf(morningFee);
                        BigDecimal lunchFeeBigDecimal = BigDecimal.valueOf(lunchFee);
                        BigDecimal resultmorning = existsActive.getBreakfastFee().multiply(morningFeeDecimal);
                        BigDecimal resultlunch = existsActive.getLunchFee().multiply(lunchFeeBigDecimal);
                        if (index != -1){
                        //计算金额
                        int oldValueMorning = values.get(index);
                        int newValueMorning = oldValueMorning + resultmorning.intValue();
                        int oldValueLunch = values2.get(index);
                        int newValueLunch = oldValueLunch + resultlunch.intValue();
                        values.set(index, newValueMorning);
                        values2.set(index, newValueLunch);
                        }
                    }
                }
            }else {
                monthlyData = wsdLeavesMapper.mealNum(schoolId, startDate, endDate);
                // 更新列表中的数据
                for (Map<String, Object> record : monthlyData) {
                    Date rechargeDate = (Date) record.get("rechargeDate");
                    String dateString = sdf.format(rechargeDate);
                    int index = -1; // 初始化下标为-1，表示未找到匹配项
                    for (int i = 0; i < labels.size(); i++) {
                        if (labels.get(i).equals(dateString)) {
                            index = i;
                            break; // 找到匹配项后退出循环
                        }
                    }
                    //餐数
                    Long morningFee = (Long) record.get("breakfastLeave");
                    Long lunchFee = (Long) record.get("lunchLeave");
                    BigDecimal morningFeeDecimal = BigDecimal.valueOf(morningFee);
                    BigDecimal lunchFeeBigDecimal = BigDecimal.valueOf(lunchFee);
                    BigDecimal resultmorning = existsActive.getBreakfastFee().multiply(morningFeeDecimal);
                    BigDecimal resultlunch = existsActive.getLunchFee().multiply(lunchFeeBigDecimal);
                    if (index != -1){
                        //计算金额
                        values.set(index, resultmorning.intValue());
                        values2.set(index, resultlunch.intValue());
                    }
                }
            }
        }


        // 结果返回格式
        ChartDataBVO result = new ChartDataBVO();
        result.setLabels(labels);
        result.setValues(values);
        result.setValues2(values2);
        return result;
    }
    //退款统计
    @Override
    public ChartDataBVO returnPeople(Integer type,LocalDateTime startDate, LocalDateTime endDate) {
        Long schoolId = null;
        SysUser sysUser = getLoginUser().getUser();
        if (!sysUser.isAdmin()) {
            schoolId = sysUser.getSchoolId();
        }
        List<Map<String, Object>> monthlyData = wsdLeavesMapper.mealNum(schoolId, startDate, endDate);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        List<String> labels = new ArrayList<>();
        List<Integer> values = new ArrayList<>();
        List<Integer> values2 = new ArrayList<>();
        if (type == 3) {
            // 创建一个包含12个月的月份列表
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.DAY_OF_MONTH, 1);
            int daysInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
            for (int i = 1; i <= daysInMonth; i++) {
                labels.add(i + "号");
                values.add(0);
                values2.add(0);
            }
            // 更新列表中的数据
            for (Map<String, Object> record : monthlyData) {
                Date rechargeDate = (Date) record.get("rechargeDate");
                String dateString = extractDay(sdf.format(rechargeDate));
                Integer month = Integer.valueOf(dateString);
                //餐数
                Long morningFee = (Long) record.get("breakfastLeave");
                Long lunchFee = (Long) record.get("lunchLeave");
                //计算金额
                values.set(month - 1, morningFee.intValue());
                values2.set(month - 1, lunchFee.intValue());
            }
        } else {
            List<String> formattedDates = getFormattedDatesBetween(startDate, endDate);
            for (String a : formattedDates) {
                labels.add(a);
                values.add(0);
                values2.add(0);
            }
            // 更新列表中的数据
            for (Map<String, Object> record : monthlyData) {
                Date rechargeDate = (Date) record.get("rechargeDate");
                String dateString = sdf.format(rechargeDate);
                int index = -1; // 初始化下标为-1，表示未找到匹配项
                for (int i = 0; i < labels.size(); i++) {
                    if (labels.get(i).equals(dateString)) {
                        index = i;
                        break; // 找到匹配项后退出循环
                    }
                }
                //餐数
                Long morningFee = (Long) record.get("breakfastLeave");
                Long lunchFee = (Long) record.get("lunchLeave");
                if (index != -1){
                    values.set(index, morningFee.intValue());
                    values2.set(index, lunchFee.intValue());
                }
            }
        }

        // 结果返回格式
        ChartDataBVO result = new ChartDataBVO();
        result.setLabels(labels);
        result.setValues(values);
        result.setValues2(values2);
        return result;
    }
    @Override
    public ChartDataVO secondleve(Integer type,LocalDateTime startDate, LocalDateTime endDate){
        Long schoolId = null;
        SysUser sysUser = getLoginUser().getUser();
        if (!sysUser.isAdmin()){
            schoolId = sysUser.getSchoolId();
        }
        List<Map<String, Object>> monthlyData = wsdPaymentRecordsMapper.getTotalFeeByWeek(schoolId,startDate,endDate);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        List<String> labels = new ArrayList<>();
        List<Integer> values = new ArrayList<>();
        //生成日期
        if (type==3) {
            // 创建一个包含12个月的月份列表
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.DAY_OF_MONTH, 1);
            int daysInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
            for (int i = 1; i <= daysInMonth; i++) {
                labels.add(i + "号");
                values.add(0);
            }
            // 更新列表中的数据
            for (Map<String, Object> record : monthlyData) {
                Date rechargeDate = (Date) record.get("rechargeDate");
                String dateString = extractDay(sdf.format(rechargeDate));
                Integer month = Integer.valueOf( dateString );
                BigDecimal totalFee = (BigDecimal) record.get("totalFee");
                values.set(month - 1, totalFee.intValue());
            }
        }else {
            List<String> formattedDates = getFormattedDatesBetween(startDate, endDate);
            for (String a : formattedDates) {
                labels.add(a);
                values.add(0);
            }
            // 更新列表中的数据
            for (Map<String, Object> record : monthlyData) {
                Date rechargeDate = (Date) record.get("rechargeDate");
                String dateString = sdf.format(rechargeDate);
                int index = -1; // 初始化下标为-1，表示未找到匹配项
                for (int i = 0; i < labels.size(); i++) {
                    if (labels.get(i).equals(dateString)) {
                        index = i;
                        break; // 找到匹配项后退出循环
                    }
                }
                BigDecimal totalFee = (BigDecimal) record.get("totalFee");
                if (index != -1){
                    values.set(index, totalFee.intValue());
                }
            }
        }

        // 结果返回格式
        ChartDataVO result = new ChartDataVO();
        result.setLabels(labels);
        result.setValues(values);
        return result;
    }

    /**
     * 第三层
     */
    @Override
    public List<FinancialOrderFoodVO> orderFood(String schoolName,LocalDateTime startDate, LocalDateTime endDate){
        List<FinancialOrderFoodVO> financialOrderFoodVOList = new ArrayList<>();
        Long schoolId = null;
        Long configId = null;
        Integer type = 1;
        SysUser sysUser = getLoginUser().getUser();
        if (!sysUser.isAdmin()){
                type = 0;
            if (sysUser.getSchoolId()==null){
                return financialOrderFoodVOList;
            }
            schoolId = sysUser.getSchoolId();
        }
        Date start = Date.from(startDate.atZone( ZoneId.systemDefault()).toInstant());
        Date end = Date.from(endDate.atZone( ZoneId.systemDefault()).toInstant());
        if (type==0) {
            configId = wsdRechargeRefundMapper.getConfigId(start,end,schoolId);
            if (configId==null){
                configId = -1L;
            }
            WsdGrades wsdGrades = new WsdGrades();
            if (schoolName!=null&&schoolName!=""){
                wsdGrades.setName( schoolName );
            }
            wsdGrades.setSchoolId( schoolId );
            startPage();
            financialOrderFoodVOList = wsdGradesMapper.financialOrderFoodVO( wsdGrades );
        }else {
            WsdSchools wsdSchools = new WsdSchools();
            if (schoolName!=null&&schoolName!=""){
                wsdSchools.setName( schoolName );
            }
            startPage();
            financialOrderFoodVOList = wsdSchoolsMapper.selectWsdSchoolsLists(wsdSchools);
        }

        for (FinancialOrderFoodVO financialOrderFoodVO : financialOrderFoodVOList){
            financialOrderFoodVO.setType( type );
            if (type==1){
                schoolId = financialOrderFoodVO.getSchoolId();
                configId = wsdRechargeRefundMapper.getConfigId(start,end,schoolId);
                if (configId==null){
                    configId = -1L;
                }
            }
            FinancialOrderFoodVO financialOrderFoodVOList1 =  wsdPaymentRecordsMapper.financialOrderFoodVOList(schoolId,startDate,endDate,configId,financialOrderFoodVO.getGradeId());
            if (financialOrderFoodVOList1==null){
                financialOrderFoodVO.setBreakfast( 0 );
                financialOrderFoodVO.setLunch( 0 );
                financialOrderFoodVO.setBreakfastNum( 0 );
                financialOrderFoodVO.setLunchNum( 0 );
                financialOrderFoodVO.setBreakfastLeave( 0 );
                financialOrderFoodVO.setLunchLeave( 0 );
                financialOrderFoodVO.setTotalLeave( 0 );
                financialOrderFoodVO.setReturnMoney( BigDecimal.ZERO );
            }else {
                //早餐午餐人数
                financialOrderFoodVO.setBreakfast( financialOrderFoodVOList1.getBreakfast() );
                financialOrderFoodVO.setLunch( financialOrderFoodVOList1.getLunch() );
                financialOrderFoodVO.setBreakfastNum( financialOrderFoodVOList1.getBreakfastNum() );
                financialOrderFoodVO.setLunchNum( financialOrderFoodVOList1.getLunchNum() );
                //请假人数
                Integer leaveNum = 0;
                FinancialOrderFoodVO aaa = wsdLeavesMapper.LeaveNum(schoolId,financialOrderFoodVO.getGradeId(),startDate,endDate);
                financialOrderFoodVO.setTotalLeave( aaa.getTotalLeave() );
                //退餐餐数
                financialOrderFoodVO.setBreakfastLeave( aaa.getBreakfastLeave() );
                financialOrderFoodVO.setLunchLeave( aaa.getLunchLeave() );
                //退款金额、日期
                financialOrderFoodVO.setReturnMoney( aaa.getReturnMoney() );
            }
        }
        return financialOrderFoodVOList;
    }
    @SneakyThrows
    @Override
    public List<FinancialLeavePeople> leavePeople(String startDate, String endDate){
        LocalDateTime startDatesTime = null;
        LocalDateTime endDatesTime = null;
        Long schoolId = null;
        Long configId = null;
//        schoolId = 28L;
        SysUser sysUser = getLoginUser().getUser();
        if (!sysUser.isAdmin()){
            schoolId = sysUser.getSchoolId();
        }
        if (startDate!=null&&endDate!=null){
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            LocalDate startDates = LocalDate.parse(startDate, formatter);
            startDatesTime = startDates.atStartOfDay();
            LocalDate endDates = LocalDate.parse(endDate, formatter);
            endDatesTime = endDates.plusDays(1).atStartOfDay().minusSeconds(1);
            SimpleDateFormat formatter2 = new SimpleDateFormat("yyyy-MM-dd");
            configId = wsdRechargeRefundMapper.getConfigId(formatter2.parse(startDate),formatter2.parse(endDate),schoolId);
        }else {
            String currentDateString = DateTimeUtil.getCurrentDateString();
            RechargeRefundVO rechargeRefundVO = wsdRechargeRefundMapper.existsActiveSemester( currentDateString, schoolId );
            if (rechargeRefundVO!=null){
                configId = rechargeRefundVO.getConfigId();
            }
        }
        if (configId==null&&!sysUser.isAdmin()){
            configId = -1L;
        }
        startPage();
        List<FinancialLeavePeople> financialLeavePeopleList = wsdLeavesMapper.leavePeople(schoolId,startDatesTime,endDatesTime,configId);
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for (FinancialLeavePeople financialLeavePeople : financialLeavePeopleList){
            String leaveTime = formatter.format(financialLeavePeople.getStartTime()) + "~" + formatter.format(financialLeavePeople.getEndTime());
            financialLeavePeople.setLeaveTime( leaveTime );
            //计算天数
            Calendar calendarStart = Calendar.getInstance();
            calendarStart.setTime(financialLeavePeople.getStartTime());
            Calendar calendarEnd = Calendar.getInstance();
            calendarEnd.setTime(financialLeavePeople.getEndTime());
            long milliseconds1 = calendarStart.getTimeInMillis();
            long milliseconds2 = calendarEnd.getTimeInMillis();
            long diff = milliseconds2 - milliseconds1;
            long diffDays = diff / (24 * 60 * 60 * 1000);
            financialLeavePeople.setLeaveDays( Double.valueOf( diffDays ) );
            if (financialLeavePeople.getLeaveDays()==0){
                financialLeavePeople.setLeaveDays( 0.5 );
            }
        }
        return financialLeavePeopleList;
    }

    public static String extractDay(String dateStr) {
        // 直接提取从索引8开始的2个字符，即为日期部分
        return dateStr.substring(8, 10);
    }
    public static List<String> getFormattedDatesBetween(LocalDateTime start, LocalDateTime end) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        long numOfDaysBetween = ChronoUnit.DAYS.between(start.toLocalDate(), end.toLocalDate()) + 1; // 加1是因为包含结束日期

        return Stream.iterate(start.toLocalDate(), date -> date.plusDays(1))
                .limit(numOfDaysBetween)
                .map(formatter::format)
                .collect(Collectors.toList());
    }
}
